/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools common
 */

#ifndef HMFS_COMMON_H
#define HMFS_COMMON_H

#include <memory>
#include <string>
#include <sys/stat.h>

#include "hmfs_command.h"
#include "hmfs_fs.h"
#include "hmfs_log.h"
#include "hmfs_utils.h"

namespace OHOS {
namespace Hmfs {
class HmfsCommon {
public:
    static HmfsCommon &GetInstance();

    int32_t LogBase2(uint32_t num);
    int32_t GetBitsInByte(unsigned char num);
    int32_t TestAndSetBitLe(uint32_t num, uint8_t *addr);
    int32_t TestAndClearBitLe(uint32_t num, uint8_t *addr);
    int32_t TestBitLe(uint32_t num, const uint8_t *addr);

    int32_t VerifyBit(uint32_t num, const uint8_t *ch);
    int32_t SetBit(uint32_t num, uint8_t *addr);
    int32_t ClearBit(uint32_t num, uint8_t *addr);

    uint64_t FindNextBitLe(const uint8_t *addr, uint64_t size, uint64_t offset);
    uint64_t FindNextZeroBitL(const uint8_t *addr, uint64_t size, uint64_t offset);

    uint32_t ExecDentryHash(int32_t encoding, int32_t casefolded, const unsigned char *name, size_t len);
    uint32_t AddrsPerInode(HmfsInode *inode);
    uint32_t AddrsPerBlock(HmfsInode *inode);
    uint32_t GetMaxFileOffset(HmfsInode *inode);

    uint32_t CalculateCrc32(uint32_t crc, void *buf, size_t len);
    int32_t CheckCrcValid(uint32_t blkCrc, void *buf, size_t len);
    uint32_t GetInodeChksum(NodeData *node, uint32_t crcSeed);
    uint32_t GetCheckpointChksum(CheckPointData *checkPoint);
    int32_t WriteInode(NodeData *inode, uint64_t blkaddr, uint32_t crcSeed);

    void GetKernelVersion(uint8_t *version);
    int32_t ReadKernelVersion(char *version, size_t len);
    bool KernelVersionSupportQuota();
    bool HasExtraIsize(HmfsInode *inode);
    int32_t GetInlineXattrAddrs(HmfsInode *inode);

    uint32_t CalcExtraIsize(void);
    void InitQfInode(NodeData *rawNode, uint32_t inodeId, time_t mtime);
    inline uint64_t GetCpCrc(CheckPointData *checkPoint)
    {
        uint64_t checkPointVersion = GetLeValue(checkPoint->checkPointVersion);
        size_t crcOffset = GetLeValue(checkPoint->checksumOffset);
        uint32_t crc = LE32ToNative(*reinterpret_cast<uint32_t*>(reinterpret_cast<unsigned char*>(checkPoint) +
            crcOffset));
        checkPointVersion |= (static_cast<uint64_t>(crc) << CRC_SHIFT);
        return NativeToLE64(checkPointVersion);
    }
    int32_t GetExtraIsize(HmfsInode *inode);
    int32_t IsPowerOf2(unsigned long n);
    double GetBestOverProvision(SuperBlockData *superBlock);
    std::vector<std::string> SplitStringList(const std::string &srcString, char delimiter);
    inline uint32_t CurAddrsPerInode(HmfsInode *inode)
    {
        return static_cast<uint32_t>(DEF_ADDRS_PER_INODE - GetExtraIsize(inode));
    }

private:
    CmdConfig &cfgPara_;

    explicit HmfsCommon(CmdConfig &cfgPara) : cfgPara_(cfgPara) {};
    static uint64_t FindFirstSet(uint8_t word);
    static uint64_t FindNextBitLeFunc(const uint8_t *addr, uint64_t size, uint64_t start, char invert);
    int32_t ReadKernelVersionFromDev(const std::string &path, char *buf, size_t len);
};
} // namespace Hmfs
} // namespace OHOS
#endif